#ifndef XGE_XRECT_H_
#define XGE_XRECT_H_
#include "xge_common_config.h"
#include "xstring.h"

namespace xge{
	// Point is the basic point type of the xge
	// user can use the specific String to initialize a
	// Point 
	class Point {
	public:
		Point( float x , float y ) :x_(x),y_(y){}
		Point():x_(0.0f),y_(0.0f) {}
	public:
		float x() const {
			return x_;
		}
		float y() const {
			return y_;
		}
		void set_x( float x ) {
			x_=x;
		}
		void set_y( float y ) {
			y_=y;
		}
		float DistanceFrom( const Point& pt ) {
			return sqrt( (x_-pt.x_)*(x_-pt.x_) + (y_-pt.y_)*(y_-pt.y_) );
		}
	public:
		// A point will be output as a string like:
		// (1.72,0.98)
		static const String& ToString( const Point& point ) ;
		// A point string will be parsed to a point
		// It will represent as:
		// [Point]:(1.72,0.98)
		static bool ToPoint(Point* point, const String& str );

		const String& ToString() const {
			return Point::ToString(*this);
		}
		bool  ToPoint( const String& str ) {
			return Point::ToPoint(this,str);
		}

	public:

		bool operator == ( const Point& pt ) const {
			return x_ == pt.x_ && y_ == pt.y_;
		}

		bool operator != ( const Point& pt ) const {
			return !((*this)==pt);
		}

	private:
		float x_,y_;
	};
	// A simple rectangle wrapper
	class Rect {
	public:
		Rect(float x,float y,float w,float h):left_up_point_(x,y),width_(w),height_(h){}
		Rect(const Point& left_up_pt,float w,float h):left_up_point_(left_up_pt),width_(w),height_(h){}
		Rect():width_(0.0f),height_(0.0f){}
	public:

		const Point& left_up_point() const {
			return left_up_point_;
		}

		float width() const {
			return width_;
		}

		float height() const {
			return height_;
		}

	public:

		void set_left_up_point( const Point& pt ) {
			left_up_point_ = pt;
		}

		void set_width( float width ) {
			width_ = width;
		}

		void set_height( float height ) {
			height_ = height;
		}
	public:
		void set_left_up_point_x( float x ) {
			left_up_point_.set_x(x);
		}
		void set_left_up_point_y( float y ) {
			left_up_point_.set_y(y);
		}
	public:
		// Get the right bottom point
		Point RightBottomPoint() const {
			return Point(left_up_point_.x()+width_,left_up_point_.y()+height_);
		}
	public:
		// Test if a collision of the point is happen
		bool IsPointIntersect( const Point& pt ) {
			return ( left_up_point_.x() > pt.x() ) && ( left_up_point_.x()+width_ < pt.x() ) 
				&&( left_up_point_.y() > pt.y() ) && ( left_up_point_.y()+height_ < pt.y() );
		}
		// Test if a collision of the rect is happen
		bool IsRectIntersect( const Rect& rect ) {
			// Allowed the return-value optimization
			const Point rect_rb(rect.RightBottomPoint());
			const Point this_rb(RightBottomPoint());

			return !( (rect.left_up_point_.x() > this_rb.x()) || (rect.left_up_point_.y() > this_rb.y()) 
				||(rect_rb.x() < left_up_point_.x()) || (rect_rb.y() < left_up_point_.y() ) );
		}

		bool operator == ( const Rect& rect ) const {
			return rect.left_up_point_ == left_up_point_ &&
				rect.width_ == width_ && rect.height_ == height_ ;
		}

		bool operator != ( const Rect& rect ) const {
			return !( (*this) == rect );
		}
	public:

		// A string that can represent a rect 
		// The rect will be represent as 
		// [Rect]:(1.34,2.079)(9.897,9.779)
		static const String& ToString( const Rect& rect ) ;   
		// A rect string is like (point.x,point.y)(width,height) 
		// example: (1.34,2.079) (9.897,9.7797) represent a rectangle
		// which has the left-bottom-point (1.34,2.079) and width = 9.897 ; height = 9.7797 
		static bool ToRect( Rect* rect , const String& str );

		const String& ToString() const {
			return Rect::ToString(*this);
		}
		bool ToRect( const String& str ) {
			return Rect::ToRect(this,str);
		}
	private:
		Point left_up_point_;
		float width_,height_;
	};

}//namespace xge


#endif// XGE_XRECT_H_